infercnv results exploration
for SCPCS000194subdiagnosis <- readr::read_tsv(
file.path("..", "..", "..", "data", "current", params$scpca_project_id, "single_cell_metadata.tsv"),
show_col_types = FALSE
) |>
dplyr::filter(scpca_sample_id == params$sample_id) |>
dplyr::pull(subdiagnosis)This notebook explores using infercnv
to estimate tumor and normal cells in SCPCS000194 from SCPCP000006. This
sample has a(n) Anaplastic subdiagnosis.
infercnv was run using the 06_inferCNV.R
script with and without a normal reference, from the same patient or
from an inter-patient pull of normal cells. We tested the impact of the
sub-selection of normal cells using either immune, and/or endothelial
cells as healthy reference. In addition, we are exploring the use of the
HMM
based CNV Prediction Methods.
infercnv currently support two models for HMM-based CNV
prediction, what we refer to as the i3 and i6 models. These are set in
the ‘infercnv::run()’ as HMM_type=‘i3’ or HMM_type=‘i6’ (i6 is default).
Each method operates on the ‘preliminary infercnv object’ which has been
processed through the standard inferCNV processing routines, involving
subtraction of signal corresponding to ‘normal (reference)’ cells and
smoothing operations.
i3 HMM is a three-state CNV model representing deletion, neutral, and amplification states.
i6 HMM: a six-state CNV model that predicts the following CNV levels:
Of note, running infercnv with a i6 HMM model is very
long, ~2hours of running time per sample, while i3 HMM model only
requires ~10min per sample.
In this notebook, we want to compare the heatmaps of CNV profiles, and evaluate how comparable are the methods and how sensible they are to key parameters such as selection of healthy reference.
Here we defined function that will be used multiple time all along the notebook.
For a Seurat object object, the function
Do_CNV_heatmap load the infercnv object
created with the script 06_infercnv.R using
reference_value as a reference and call the function
SCpubr::do_CopyNumberVariantPlot to plot the mean CNV score
in each group defined in group.by.
object is the Seurat object
infercnv_obj is the infercnv
object
group.by is the metadata used for grouping the
violin plots
Do_CNV_heatmap <- function(object, infercnv_obj, group.by){
out <- SCpubr::do_CopyNumberVariantPlot(sample = object,
infercnv_object = infercnv_obj,
using_metacells = FALSE,
chromosome_locations = SCpubr::human_chr_locations,
return_object = FALSE,
group.by = group.by
)
out <- out +
ggtitle(glue::glue("Copy Number Variant Plot, ", reference_value)) +
ylab(label = "")
return(out)
}For a Seurat object an infercnv object
created with the script 06_infercnv.R using
reference_value as a reference, the function
Do_CNV_score calculate a CNV score per cell. The score is
calculated based on the biostar discussion. The
function Do_CNV_score returns the Seurat
object with an additional metadata named
CNV-score_{reference_value}.
reference_value is the selection of normal cells used
for infercnvseurat_object and infercnv_obj are the
Seuratand infercnv object created with the
script 06_infercnv.RFor a Seurat object objectand a metadata
metadata, the function visualize_metadata will
plot FeaturePlot and BarPlot
object is the Seurat object
meta the gene or quantitative value to be
plotted
group.by is the metadata used for grouping the
violin plots
visualize_metadata <- function(object, meta, group.by){
if(is.numeric(object@meta.data[,meta])){
d <- SCpubr::do_FeaturePlot(object,
features = meta,
pt.size = 0.2,
legend.width = 0.5,
legend.length = 5,
legend.position = "right") + ggtitle(meta)
b <- SCpubr::do_ViolinPlot(object,
features = meta,
ncol = 1,
group.by = group.by,
legend.position = "none")
return(d + b + plot_layout(ncol = 2, widths = c(2,4)))
}
else{
d <- SCpubr::do_DimPlot(object, reduction="umap", group.by = group.by, label = TRUE, repel = TRUE) + ggtitle(paste0(meta," - umap")) + theme(text=element_text(size=18))
b <- SCpubr::do_BarPlot(sample = object,
group.by = meta,
split.by = group.by,
position = "fill",
font.size = 10,
legend.ncol = 3) +
ggtitle("% cells")+
xlab(print(group.by)) +
theme(text=element_text(size=18))
return(d + b + plot_layout(ncol = 2, widths = c(2,4)))
}
}For a Seurat object objectand a features
features, the function visualize_feature will
plot FeaturePlot and ViolinPlot
object is the Seurat object
features the gene or quantitative value to be
plotted
group.by is the metadata used for grouping the
violin plots
visualize_feature <- function(object, features, group.by ){
d <- SCpubr::do_FeaturePlot(object,
features = features,
pt.size = 0.2,
legend.width = 0.5,
legend.length = 5,
legend.position = "right") + ggtitle(features)
b <- SCpubr::do_ViolinPlot(object,
features = features,
ncol = 1,
group.by = group.by,
legend.position = "none",
assay = "SCT") + ylab(features)
return(d + b + plot_layout(ncol = 2, widths = c(2,4)))
}For a Seurat object objectand a features
features, the function visualize_feature will
plot FeaturePlot and ViolinPlot
object is the Seurat object
features the gene or quantitative value to be
plotted
group.by is the metadata used for grouping the
violin plots
The input for this notebook are the results of
06_inferCNV.R
Here we plot the output of infercnv as heatmaps of CNV.
We first look at the png file generated by the infercnv
function. We then used the infercnv object to look at mean
CNV value across compartments (immune, endothelial, stroma and fetal
nephron).
infercnv_obj <- list()
for(reference_value in c("reference-none", "reference-immune", "reference-endothelium", "reference-both")){
infercnv_obj[[reference_value]] <- readRDS(file.path(result_dir, glue::glue(reference_value, "_HMM-no") , glue::glue("06_infercnv_", params$sample_id, "_", reference_value, "_HMM-no.rds")))
print(Do_CNV_heatmap(object = srat, infercnv_obj = infercnv_obj[[reference_value]], group.by = "fetal_kidney_predicted.compartment"))
}
These heatmaps emphasize the importance of the selection of normal cells
prior the inference of CNV. The normal reference should contain as much
cell types as possible, in order to minimize false positive CNV. In our
case, we should take immune and entodethial cells when possible.
Of note: By default if no reference is provided,
infercnv take the mean of expression as normal reference.
The risk is that the main cell population (in our case the fetal nephron
compartment) might be mistaken as the normal baseline.
We want to calculate a single CNV score and asess if/how it can be use to define cells with CNV versus stable/normal cells. We defined the score as discribed in the biostar discussion.
We would expect:
immune and endothelial cells to have a low CNV score
fetal nephron and stroma cells to have low to high CNV score.
Ideally, the CNV score distribution should show two peaks, one for the normal cells with no CNV, one for cancer cells with more genomic rearrangements.
for(reference_value in c("reference-none", "reference-immune", "reference-endothelium", "reference-both")){
srat <- Do_CNV_score(srat,infercnv_obj = infercnv_obj[[reference_value]], reference_value)
p1 <- visualize_feature(srat, glue::glue("CNV-score_", reference_value) , group.by = "fetal_kidney_predicted.compartment" )
p2 <- visualize_density(srat, features=glue::glue("CNV-score_", reference_value), group.by = "fetal_kidney_predicted.compartment")
print(p1 + p2 + plot_layout(ncol = 3, widths = c(1,2,2)))
}This unique CNV score does not look promising. We will not use this score in future notebooks.
We might have to select chromosomes we would like to look at, i.e. the one relevant for Wilms tumor (1p, 1q, chr17).
We then explore infercnv results generated with immune and endothelial cells as reference, using a HMM-i3 prediction models.
Seurat objectWe load the Seurat object generated in
06_infercnv.R
For each chromosome, we look at the repartition of the
proportion_cnv_ in cells labeled as immune, endothelial,
stroma and fetal nephron. proportion_cnv_ is the proportion
in number of genes that are part of any cnv/loss/duplication in the
given chr.
This should allow a quick visual check that immune and endothelial cells do not expressed any CNV. If not, we should check if genes driving the CNV score are not key immune or endothelium genes.
The umap reduction visualization might allow the
identification of cluster(s) of normal cells with no CNV.
for(i in 1:22){
print(visualize_feature(srat_i3, features=glue::glue("proportion_cnv_chr", i), group.by = "fetal_kidney_predicted.compartment"))
}For each chromosome, we look at the distribution of the
proportion_cnv_ in cells labeled as immune, endothelial,
stroma and fetal nephron. proportion_cnv_ is the proportion
in number of genes that are part of any cnv/loss/duplication in the
given chr.
We are quite confident that immune and endothelial cells are well
identified by label transfer done in
02b_label-transfer_fetal_kidney_reference_Stewart.Rmd. The
distribution of CNV for endothelial and immune cells should thus be a
single peak center on 0.
We do not know if fetal nephron and stroma cells are a mix of normal and cancer cells. Would they be a group of normal cells, we should expect a single peak center on 0 for every chromosome. As we expect to have a large number of cancer with heterogeneous CNV, we should see multiple peaks.
for(i in 1:22){
print(visualize_density(srat_i3, features=glue::glue("proportion_cnv_chr", i), group.by = "fetal_kidney_predicted.compartment"))
}The Dotplot representation summarizes the percentage of
cells in each compartment with cnv in each of the 22 chromosomes.
The HMM-i3 prediction model with intra-patient reference (composed of immune and endothelium cells) perform really well in identifying Wilms tumor relevant CNV. No false positive CNV are observed in the immune and endothelium compartment.
DotPlot(srat_i3, features = colnames(srat_i3@meta.data)[grepl("has_cnv_chr", colnames(srat_i3@meta.data))], group.by = "fetal_kidney_predicted.compartment", assay = "SCT") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))## Warning: Scaling data with a low number of groups may produce misleading results
Here, we try to calculate a single CNV score and assess its potential in iditenfying cells with CNV versus normal cells without CNV.
We simply checked for each chromosome if the cell
has_cnv_chr. Would the cell have one or more chromosome
with CNV, the global has_cnv_score will be TRUE. Else, the
cell will have a has_cnv_score set to FALSE.
meta <- srat_i3@meta.data
meta$has_cnv_score <- rowSums(meta[,grepl("has_cnv_chr", colnames(meta))])
meta$has_cnv_score[meta$has_cnv_score > 1] <- "CNV"
# we know that some immune cells might have false positive CNV
meta$has_cnv_score[meta$has_cnv_score %in% c(0,1)] <- "no CNV"
srat_i3 <- AddMetaData(srat_i3, meta$has_cnv_score, col.name = "has_cnv_score")We identified clusters with no/low CNV while the majority of the
Seurat cluster present CNV on more than one chromosome.
## [1] "seurat_clusters"
Immune and endothelial cells have a majority of cells with no/low CNV profile, which confirm their annotation as normal cells. The fetal nephron and stroma copartments are mainly composed of cancer cells with more than one chromosome affected by a CNV.
## [1] "fetal_kidney_predicted.compartment"
We then explore infercnv results generated with immune
and endothelial cells as reference, using a HMM-i6
model.
Seurat objectWe load the Seurat object generated in
06_infercnv.R
For each chromosome, we look at the repartition of the
proportion_cnv_ in cells labeled as immune, endothelial,
stroma and fetal nephron. proportion_cnv_ is the proportion
in number of genes that are part of any cnv/loss/duplication in the
given chr.
for(i in 1:22){
print(visualize_feature(srat_i6, features=glue::glue("proportion_cnv_chr", i), group.by = "fetal_kidney_predicted.compartment"))
}For each chromosome, we look at the distribution of the
proportion_cnv_ in cells labeled as immune, endothelial,
stroma and fetal nephron. proportion_cnv_ is the proportion
in number of genes that are part of any cnv/loss/duplication in the
given chr.
We are quite confident that immune and endothelial cells are well
identified by label transfer done in
02b_label-transfer_fetal_kidney_reference_Stewart.Rmd. The
distribution of CNV for endothelial and immune cells should thus be a
single peak center on 0.
We do not know if fetal nephron and stroma cells are a mix of normal and cancer cells. Would they be a group of normal cells, we should expect a single peak center on 0 for every chromosome. As we expect to have a large number of cancer with heterogeneous CNV, we should see multiple peaks.
for(i in 1:22){
print(visualize_density(srat_i6, features=glue::glue("proportion_cnv_chr", i), group.by = "fetal_kidney_predicted.compartment"))
}The Dotplot representation summarizes the percentage of
cells in each compartment with cnv in each of the 22 chromosomes.
The HMM-i3 prediction model with intra-patient reference (composed of immune and endothelium cells) perform really well in identifying Wilms tumor relevant CNV. No false positive CNV are observed in the immune and endothelium compartment.
DotPlot(srat_i6, features = colnames(srat_i6@meta.data)[grepl("has_cnv_chr", colnames(srat_i6@meta.data))], group.by = "fetal_kidney_predicted.compartment", assay = "SCT") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))## Warning: Scaling data with a low number of groups may produce misleading results
Finally, we try to calculate single CNV score and assess its potential in iditenfying cells with CNV versus normal cells without CNV.
We simply checked for each chromosome if the cell
has_cnv_chr. Would the cell have one or more chromosome
with CNV, the global has_cnv_score will be TRUE. Else, the
cell will have a has_cnv_score set to FALSE.
meta <- srat_i6@meta.data
meta$has_cnv_score <- rowSums(meta[,grepl("has_cnv_chr", colnames(meta))])
meta$has_cnv_score[meta$has_cnv_score > 1] <- "CNV"
# we know that some immune cells might have false positive CNV
meta$has_cnv_score[meta$has_cnv_score %in% c(0,1)] <- "no CNV"
srat_i6 <- AddMetaData(srat_i6, meta$has_cnv_score, col.name = "has_cnv_score")## [1] "seurat_clusters"
## [1] "fetal_kidney_predicted.compartment"
We lastly explore infercnv results generated with a pull
of immune and endothelial cells from different Wilms tumor samples as
reference, using a HMM-i3 prediction model.
The selection of normal cells to be spiked-in as a normal reference
prior running infercnv has been performed in
`06a_build-normal-cell_reference.R. We selected samples that haven’t
been pre-treated with chemotherapies. Indeed, even if normal cells
shouldn’t be affected by chemotherapy in terms of CNV, we are not sure
how chemotherapies can affect the CNV profile of normal cells. We thus
decided to only take endothelial and immune cells from non-treated
samples to build the reference of normal cells.
Seurat objectWe load the Seurat object generated in
06_infercnv.R and transfer the infercnv
metadata to the main Seurat object of sample SCPCS000194
saved in 02b-fetal_kidney_label-transfer_SCPCS000194.Rds.
Such a transfer is required as the merged Seurat object
+ spike-in cells does not contained the umap reduction.
seurat_full <- readRDS(file.path(module_base, "results", params$sample_id, glue::glue("06_infercnv_HMM-i3_", params$sample_id, "_reference-pull.rds")))
# subset non spike-in cells
keep_cells <- colnames(seurat_full)[!grepl("spike", colnames(seurat_full))]
seurat <- subset(seurat_full, cells = keep_cells)
meta <- seurat@meta.data
# merge the new info into the srat metadata
srat <- AddMetaData(srat, meta[,grepl("_cnv_chr", colnames(meta))], col.name = colnames(meta[grepl("_cnv_chr", colnames(meta))]))For each chromosome, we look at the repartition of the
proportion_cnv_ in cells labeled as immune, endothelial,
stroma and fetal nephron. proportion_cnv_ is the proportion
in number of genes that are part of any cnv/loss/duplication in the
given chr.
This should allow a quick visual check that immune and endothelial cells do not expressed any CNV. If so, we should check if genes driving the CNV score are not key immune or endothelium genes.
Also, we should visualize if one area of the umap do not have CNV and could be identify as additional normal cell subset.
for(i in 1:22){
print(visualize_feature(srat, features=glue::glue("proportion_cnv_chr", i), group.by = "fetal_kidney_predicted.compartment"))
}For each chromosome, we look at the distribution of the
proportion_cnv_ in cells labeled as immune, endothelial,
stroma and fetal nephron. proportion_cnv_ is the proportion
in number of genes that are part of any cnv/loss/duplication in the
given chr.
We are quite confident that immune and endothelial cells are well
identified by label transfer done in
02b_label-transfer_fetal_kidney_reference_Stewart.Rmd. The
distribution of CNV for endothelial and immune cells should thus be a
single peak center on 0.
We do not know if fetal nephron and stroma cells are a mix of normal and cancer cells. Would they be a group of normal cells, we should expect a single peak center on 0 for every chromosome. As we expect to have a large number of cancer with heterogeneous CNV, we should see multiple peaks.
for(i in 1:22){
print(visualize_density(srat, features=glue::glue("proportion_cnv_chr", i), group.by = "fetal_kidney_predicted.compartment"))
}The Dotplot representation summarizes the percentage of
cells in each compartment with cnv in each of the 22 chromosomes.
The HMM-i3 prediction model with inter-patient reference (composed of immune and endothelium cells) perform quite well in identifying Wilms tumor relevant CNV. However, sample variation induced false positive CNV such as CNV on chromosome 5 and 13 observed in the endothelium compartment.
DotPlot(srat, features = colnames(srat@meta.data)[grepl("proportion_cnv_chr", colnames(srat@meta.data))], group.by = "fetal_kidney_predicted.compartment", assay = "SCT") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))## Warning: Scaling data with a low number of groups may produce misleading results
Finally, we try to calculate single CNV score and assess its potential in iditenfying cells with CNV versus normal cells without CNV.
We simply checked for each chromosome if the cell
has_cnv_chr. Would the cell have three or more chromosome
with CNV, the global has_cnv_score will be TRUE. Else, the
cell will have a has_cnv_score set to FALSE.
Of note, as we know that the use of a ~universal inter-patient reference of normal cells can induce false positive CNV in some chromosomes, we decided to allow up to 2 CNV in normal cells.
meta <- srat@meta.data
meta$has_cnv_score <- rowSums(meta[,grepl("has_cnv_chr", colnames(meta))])
meta$has_cnv_score[meta$has_cnv_score > 2] <- "CNV"
# we know that some immune cells might have false positive CNV
meta$has_cnv_score[meta$has_cnv_score %in% c(0,1, 2)] <- "no CNV"
srat <- AddMetaData(srat, meta$has_cnv_score, col.name = "has_cnv_score")## [1] "seurat_clusters"
## [1] "fetal_kidney_predicted.compartment"
We compare here the binary CNV scores calculated with the three HMM prediction models:
HMM-i3 with inter-patient endothelial and immunce cells as reference
HMM-i3 with intra-patient endothelial and immunce cells as reference
HMM-i6 with intra-patient endothelial and immunce cells as reference
p1 <- SCpubr::do_DimPlot(srat, "has_cnv_score", plot.title = "inter-patient reference, HMM-i3", reduction = "umap")
p2 <- SCpubr::do_DimPlot(srat_i3, "has_cnv_score", plot.title = "intra-patient reference, HMM-i3", reduction = "umap")
p3 <- SCpubr::do_DimPlot(srat_i6, "has_cnv_score", plot.title = "intra-patient reference, HMM-i6", reduction = "umap")
p1 + p2 + p3 + plot_layout(ncol = 3)We should run infercnv with the most diverse normal
reference as possible, including different cell types. Providing no
reference is not a good option, as we think that most of the cells are
cancer cells with few CNV. In our case, we advise taking at least immune
and endothelial cells as normal reference.
The HMM prediction models help exploring the
infercnv results. In this notebook, we have compared three
HMM prediction models:
HMM-i3 with inter-patient endothelial and immunce cells as reference
HMM-i3 with intra-patient endothelial and immunce cells as reference
HMM-i6 with intra-patient endothelial and immunce cells as reference
Globally, the three scores seems to drive similar conclusions, with the majority of fetal nephron and stroma cells being cancer cells, at least in the sample selected.
The HMM-i3 model with inter-patient endothelial and immunce cells as reference has the advantage to be usable for all Wilms tumor samples, including the ones with a very low number of immune and/or endothelial cells.
The HMM-i3 model with intra-patient endothelial and immunce cells as reference seems to be the cleaner, ~fast to run (10 minutes per samples) and is more precise than the HMM-i3 with the inter-patient reference.
The HMM-i6 model with intra-patient endothelial and immunce cells as reference is very slow (~2 hours per sample) and couldn’t be used for the entire cohorte. It is more noisy than the i3 version. However, it could have the potential to detect cancer cells with very low CNV profile.
Surprisingly, running infercnv with emdothelial and
immune cells from (i) the same patient or (ii) a set of Wilms tumor
patients do not seem to affect drastically the results. Some false
positive CNV might occur in every patient due to the inter-patient
variability. By comparing the results in conditions (i) and (ii), we
should be able to understand which false positive are recurrent and do
not take them into account.
# record the versions of the packages used in this analysis and other environment information
sessionInfo()## R version 4.4.1 (2024-06-14)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 22.04.4 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.20.so; LAPACK version 3.10.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## time zone: Europe/Vienna
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] ggdist_3.3.2 optparse_1.7.5 Seurat_5.1.0 SeuratObject_5.0.2 sp_2.1-4 patchwork_1.2.0 ggplot2_3.5.1 SCpubr_2.0.2 infercnv_1.20.0
##
## loaded via a namespace (and not attached):
## [1] fs_1.6.4 matrixStats_1.3.0 spatstat.sparse_3.1-0 bitops_1.0-8 httr_1.4.7 RColorBrewer_1.1-3 doParallel_1.0.17
## [8] tools_4.4.1 sctransform_0.4.1 utf8_1.2.4 R6_2.5.1 DT_0.33 lazyeval_0.2.2 uwot_0.2.2
## [15] withr_3.0.1 gridExtra_2.3 parallelDist_0.2.6 progressr_0.14.0 argparse_2.2.3 cli_3.6.3 Biobase_2.64.0
## [22] formatR_1.14 spatstat.explore_3.3-2 fastDummies_1.7.4 sandwich_3.1-1 sass_0.4.9 labeling_0.4.3 mvtnorm_1.3-1
## [29] spatstat.data_3.1-2 readr_2.1.5 ggridges_0.5.6 pbapply_1.7-2 yulab.utils_0.1.7 parallelly_1.38.0 limma_3.60.4
## [36] rstudioapi_0.16.0 RSQLite_2.3.7 generics_0.1.3 gridGraphics_0.5-1 vroom_1.6.5 gtools_3.9.5 ica_1.0-3
## [43] spatstat.random_3.3-1 dplyr_1.1.4 distributional_0.5.0 Matrix_1.7-0 futile.logger_1.4.3 fansi_1.0.6 S4Vectors_0.42.1
## [50] abind_1.4-5 lifecycle_1.0.4 multcomp_1.4-26 yaml_2.3.10 edgeR_4.2.1 SummarizedExperiment_1.34.0 gplots_3.1.3.1
## [57] SparseArray_1.4.8 Rtsne_0.17 grid_4.4.1 blob_1.2.4 promises_1.3.0 crayon_1.5.3 miniUI_0.1.1.1
## [64] lattice_0.22-6 cowplot_1.1.3 KEGGREST_1.44.1 pillar_1.9.0 knitr_1.48 GenomicRanges_1.56.1 future.apply_1.11.2
## [71] codetools_0.2-20 leiden_0.4.3.1 glue_1.7.0 spatstat.univar_3.0-0 data.table_1.16.0 vctrs_0.6.5 png_0.1-8
## [78] spam_2.10-0 gtable_0.3.5 assertthat_0.2.1 cachem_1.1.0 xfun_0.47 S4Arrays_1.4.1 mime_0.12
## [85] libcoin_1.0-10 coda_0.19-4.1 survival_3.7-0 DElegate_1.2.1 SingleCellExperiment_1.26.0 iterators_1.0.14 statmod_1.5.0
## [92] fitdistrplus_1.2-1 TH.data_1.1-2 ROCR_1.0-11 nlme_3.1-166 bit64_4.0.5 RcppAnnoy_0.0.22 GenomeInfoDb_1.40.1
## [99] rprojroot_2.0.4 bslib_0.8.0 irlba_2.3.5.1 KernSmooth_2.23-24 colorspace_2.1-1 BiocGenerics_0.50.0 DBI_1.2.3
## [106] tidyselect_1.2.1 bit_4.0.5 compiler_4.4.1 DelayedArray_0.30.1 plotly_4.10.4 scales_1.3.0 caTools_1.18.2
## [113] lmtest_0.9-40 stringr_1.5.1 digest_0.6.37 goftest_1.2-3 spatstat.utils_3.1-0 rmarkdown_2.28 XVector_0.44.0
## [120] htmltools_0.5.8.1 pkgconfig_2.0.3 MatrixGenerics_1.16.0 highr_0.11 fastmap_1.2.0 rlang_1.1.4 htmlwidgets_1.6.4
## [127] UCSC.utils_1.0.0 shiny_1.9.1 jquerylib_0.1.4 farver_2.1.2 zoo_1.8-12 jsonlite_1.8.8 magrittr_2.0.3
## [134] modeltools_0.2-23 GenomeInfoDbData_1.2.12 ggplotify_0.1.2 dotCall64_1.1-1 munsell_0.5.1 Rcpp_1.0.13 viridis_0.6.5
## [141] ape_5.8 reticulate_1.38.0 stringi_1.8.4 zlibbioc_1.50.0 MASS_7.3-61 plyr_1.8.9 parallel_4.4.1
## [148] listenv_0.9.1 ggrepel_0.9.5 forcats_1.0.0 deldir_2.0-4 Biostrings_2.72.1 splines_4.4.1 tensor_1.5
## [155] hms_1.1.3 locfit_1.5-9.10 igraph_2.0.3 fastcluster_1.2.6 spatstat.geom_3.3-2 RcppHNSW_0.6.0 reshape2_1.4.4
## [162] stats4_4.4.1 futile.options_1.0.1 evaluate_0.24.0 RcppParallel_5.1.9 lambda.r_1.2.4 renv_1.0.7 tzdb_0.4.0
## [169] phyclust_0.1-34 foreach_1.5.2 httpuv_1.6.15 RANN_2.6.2 tidyr_1.3.1 getopt_1.20.4 purrr_1.0.2
## [176] polyclip_1.10-7 future_1.34.0 scattermore_1.2 coin_1.4-3 xtable_1.8-4 RSpectra_0.16-2 later_1.3.2
## [183] viridisLite_0.4.2 rjags_4-16 tibble_3.2.1 memoise_2.0.1 AnnotationDbi_1.66.0 IRanges_2.38.1 cluster_2.1.6
## [190] globals_0.16.3